package qinggui.mlz.console.rocketmq.consumer;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import qinggui.mlz.module.category.mapper.CategoryMapper;
import qinggui.mlz.module.rocketmq.event.CategoryDeleteEvent;
import qinggui.mlz.module.star.entity.Star;
import qinggui.mlz.module.star.mapper.StarMapper;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
@RocketMQMessageListener(
        topic = "category-delete-topic",
        consumerGroup = "category-delete-consumer-group",
        maxReconsumeTimes = 5)// 5 次后进入死信队列 %DLQ%category-delete-consumer-group
public class CategoryDeleteConsumer implements RocketMQListener<CategoryDeleteEvent> {

    @Resource
    private StarMapper starMapper;
    @Resource
    private CategoryMapper categoryMapper;
    // 用Redis 幂等控制
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 监听类目删除消息,每来一个消息就执行这个方法
     *
     * @param categoryDeleteEvent 类目删除消息
     */
    @Override
    public void onMessage(CategoryDeleteEvent categoryDeleteEvent) {
        // 1. 幂等（redis setNX 30 min）
        String key = "rmq:cat:del:" + categoryDeleteEvent.getTampStamp();
        // 只有当key不存在时候，才设置值，并给key加30分钟过期时间。
        // 用 Redis 的 SETNX 加 30 分钟过期，一次性解决幂等 + 自动清理。
        Boolean b = redisTemplate.opsForValue().setIfAbsent(key, "1", Duration.ofMinutes(30));
        if (Boolean.FALSE.equals(b)) {
            // 重复消费，打印警告日志并直接返回，不再执行业务逻辑
            log.warn("重复消费 {}", categoryDeleteEvent.getCategoryIds());
            return;
        }
        // 从事件对象中取出要删除的类目 ID 列表
        List<Long> categoryIds = categoryDeleteEvent.getCategoryIds();
        // 如果列表不为空，则执行批量软删球星操作
        if (!categoryIds.isEmpty()) {
            List<Star> stars = categoryMapper.queryInDeletes(categoryIds);
            List<Long> starIds = new ArrayList<>();
            for (Star star : stars) {
                starIds.add(star.getId());
            }
            starMapper.deleteInStarIds(starIds, categoryDeleteEvent.getTampStamp());
            // 打印 info 级别日志，记录本次删除的类目 ID
            log.info("异步删除球星完成，类目={}", categoryIds);
        }
    }
}
